package com.huifenqi.sidecar.config;

import com.ecwid.consul.v1.agent.model.NewService;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.actuator.HasFeatures;
import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.consul.discovery.ConsulDiscoveryProperties;
import org.springframework.cloud.consul.discovery.HeartbeatProperties;
import org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration;
import org.springframework.cloud.consul.serviceregistry.ConsulRegistrationCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;

import java.net.URI;
import java.util.List;

@Configuration
@EnableConfigurationProperties
@ConditionalOnProperty(value = "spring.cloud.consul.sidecar.enabled", matchIfMissing = true)
public class SidecarConfiguration {

    @Bean
    public HasFeatures Feature() {
        return HasFeatures.namedFeature("Consul Sidecar", SidecarConfiguration.class);
    }

    @Bean
    public SidecarProperties sidecarProperties() {
        return new SidecarProperties();
    }


    @Bean
    public LocalApplicationHealthIndicator localApplicationHealthIndicator() {
        return new LocalApplicationHealthIndicator();
    }

    @Bean
    public SidecarController sidecarController() {
        return new SidecarController();
    }

    @Configuration
    protected static class ConsulInstanceConfigBeanConfiguration {

        @Autowired
        private SidecarProperties sidecarProperties;

        @Value(value = "${management.port:${MANAGEMENT_PORT:#{null}}}")
        private Integer managementPort;

        @Value("${server.port:${SERVER_PORT:${PORT:8080}}}")
        private int serverPort = 8080;

        @Value("${management.context-path:${MANAGEMENT_CONTEXT_PATH:#{null}}}")
        private String managementContextPath;

        @Value("${server.context-path:${SERVER_CONTEXT_PATH:/}}")
        private String serverContextPath = "/";


        @Autowired
        private ConfigurableEnvironment env;

        @Bean
        public ConsulAutoRegistration consulRegistration(ConsulDiscoveryProperties properties, AutoServiceRegistrationProperties registrationProperties, ApplicationContext applicationContext,
                                                         ObjectProvider<List<ConsulRegistrationCustomizer>> registrationCustomizers, HeartbeatProperties heartbeatProperties) {
            return registration(properties, registrationProperties, applicationContext, registrationCustomizers.getIfAvailable(), heartbeatProperties);
        }

        private ConsulAutoRegistration registration(ConsulDiscoveryProperties properties, AutoServiceRegistrationProperties registrationProperties, ApplicationContext context,
                                                    List<ConsulRegistrationCustomizer> registrationCustomizers,
                                                    HeartbeatProperties heartbeatProperties) {

            int port = sidecarProperties.getPort();
            String hostname = sidecarProperties.getHostname();
            String ipAddress = sidecarProperties.getIpAddress();
            if (!StringUtils.hasText(hostname)) {
                hostname = properties.getHostname();
            }
            URI healthUri = sidecarProperties.getHealthUri();
            URI homePageUri = sidecarProperties.getHomePageUri();
            NewService service = new NewService();

            String appName = ConsulAutoRegistration.getAppName(properties, env);
            service.setId(ConsulAutoRegistration.getInstanceId(properties, context));
            if (!properties.isPreferAgentAddress()) {
                service.setAddress(hostname);
            }
            service.setName(ConsulAutoRegistration.normalizeForDns(appName));
            service.setTags(ConsulAutoRegistration.createTags(properties));

            if (properties.getPort() != null) {
                service.setPort(port);
                ConsulAutoRegistration.setCheck(service, registrationProperties, properties, context, heartbeatProperties);
            }

            ConsulAutoRegistration registration = new ConsulAutoRegistration(service, registrationProperties, properties, context, heartbeatProperties);
            ConsulAutoRegistration.customize(registrationCustomizers, registration);
            return registration;
        }
    }

}